/*
 * @Author: mat
 * @Date: 2020-04-01 15:45:33
 * @LastEditTime: 2020-05-19 15:36:41
 * @LastEditors: Please set LastEditors
 * @Description: 基于Iexplorer二次开发的拓展方法
 * @FilePath: \vue-cesium-template\src\utils\earth.js
 */

/* eslint-disable*/
import axios from 'axios'
import store from '../store'
import { debounce, throttle, simpleThrottle } from './utils.js'
class Earth {
  constructor() {
    this.viewer = {}
    this.baseImageLayer = {}
    this.localImageLayer = {}
    this.baseImageLayerUrl = 'http://mt1.google.cn/vt/lyrs=s&hl=zh-CN&x={x}&y={y}&z={z}&s=Gali'
    this.terrainLayerUrl = config.icenter_url + '/tilecache/service/terrain/Global_DEM-TERRAIN-4326'
    this.group = {}
    this.modelGraphic = null
    this.dataJson = {}
    this.TargetHistory = {}
    this.timeout = null
  }
  init(earthID) {
    // 初始化地球
    this.viewer = new GV.GeoCanvas(earthID, {
      shouldAnimate: true, //启用动画
      timeline: true,
      animation: true,
      baseLayerPicker: false,
      skyBox: new Cesium.SkyBox({
        sources: {
          positiveX: 'images/SkyBox/mx.jpg',
          negativeX: 'images/SkyBox/mx.jpg',
          positiveY: 'images/SkyBox/py.jpg',
          negativeY: 'images/SkyBox/my.jpg',
          positiveZ: 'images/SkyBox/pz.jpg',
          negativeZ: 'images/SkyBox/mz.jpg'
        }
      })
    })

    var options = {}
    // 用于在使用重置导航重置地图视图时设置默认视图控制。接受的值是Cesium.Cartographic 和Cesium.Rectangle.
    options.defaultResetView = Cesium.Cartographic.fromDegrees(110, 30, 2000000)
    // 用于启用或禁用罗盘。true是启用罗盘，false是禁用罗盘。默认值为true。如果将选项设置为false，则罗盘将不会添加到地图中。
    options.enableCompass = true
    // 用于启用或禁用缩放控件。true是启用，false是禁用。默认值为true。如果将选项设置为false，则缩放控件 将不会添加到地图中。
    options.enableZoomControls = true
    // 用于启用或禁用距离图例。true是启用，false是禁用。默认值为true。如果将选项设置为false，距离图例将不会添加到地图中。
    options.enableDistanceLegend = true
    // 用于启用或禁用指南针外环。true是启用，false是禁用。默认值为true。如果将选项设置为false，则该环将可见但无效。
    options.enableCompassOuterRing = true
    options.mapMode2D = Cesium.MapMode2D.ROTATE

    this.viewer.extend(Cesium.viewerCesiumNavigationMixin, options)

    // this.viewer.scene.morphTo2D(0); //切换二维
    this.viewer.scene.debugShowFramesPerSecond = true //显示帧率
    this.setGlobalHandler()
    this.changeTimeLine()
    this.dynamicChangeTime()
    let that = this
    // 全球影像
    this.baseImageLayer = this.viewer.imageryLayers.addImageryProvider(
      new Cesium.UrlTemplateImageryProvider({
        url: that.baseImageLayerUrl
      })
    )

    // this.IEflyTo(
    //   {
    //     lon: 118.89758500436089,
    //     lat: 33.052020819327375,
    //     alt: 590123.0816038932,
    //     heading: 358.4052051397172,
    //     pitch: -58.624731557160786,
    //     roll: 359.999937758499
    //   },
    //   3,
    //   1000
    // )
  }
  // 设置cesium全局事件
  setGlobalHandler() {
    let that = this
    // 注册cesium全局事件
    const leftClickHandler = new Cesium.ScreenSpaceEventHandler(that.viewer.canvas)
    const mousemoveHandler = new Cesium.ScreenSpaceEventHandler(that.viewer.canvas)
    leftClickHandler.setInputAction(function(movement) {
      const pickedObject = that.viewer.scene.pick(movement.position)
      console.log(that.cartesian2ToCartographic(movement.position))
      // ie中通过GraphicLayer加载的对象可以通过该方法拾取
      // const pickedObject = that.viewer.graphicLayer.pickByCoordinate(movement.position.x, movement.position.y)
      if (Cesium.defined(pickedObject) && Cesium.defined(pickedObject.id) && typeof pickedObject.id.leftClick === 'function') {
        pickedObject.id.leftClick(pickedObject.id)
      }
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK)

    var debounceFunc = debounce(that.mouseMoveEvent, 1000, true, that)
    var throttleFunc = throttle(that.mouseMoveEvent, 100, that, { leading: false })
    var simpleThrottleFunc = simpleThrottle(that.mouseMoveEvent, 100, that)
    mousemoveHandler.setInputAction(function mouseMove(movement) {
      // debounceFunc(movement)
      // throttleFunc(movement)
      simpleThrottleFunc(movement)
      // that.mouseMoveEvent(movement)
    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
  }
  // cesium鼠标浮动事件
  mouseMoveEvent(movement) {
    const pickedObject = this.viewer.scene.pick(movement.endPosition)
    const iepickedObject = this.viewer.graphicLayer.pickByCoordinate(movement.endPosition.x, movement.endPosition.y)
    // entity 如果包含属性cursor，鼠标浮动时变小手
    if (
      (Cesium.defined(pickedObject) && Cesium.defined(pickedObject.id) && pickedObject.id.cursor === true) ||
      (iepickedObject && iepickedObject.cursor)
    ) {
      this.viewer.canvas.style.cursor = 'pointer'
    } else {
      this.viewer.canvas.style.cursor = 'default'
    }
    // 如果为该entity添加了鼠标浮动事件，调用该方法
    // 所有infoBox都绑定 vuex 中的infoBoxShow，在鼠标浮动时，先将其设置为false
    store.dispatch('layerManage/setInfoBoxShowFun', false)
    if (Cesium.defined(pickedObject) && Cesium.defined(pickedObject.id) && typeof pickedObject.id.mouseMove === 'function') {
      pickedObject.id.mouseMove(pickedObject.id, movement.endPosition)
    }
    // iepickedObject 的判断
    if (iepickedObject && iepickedObject.mouseMove && typeof iepickedObject.mouseMove === 'function') {
      iepickedObject.mouseMove(iepickedObject, movement.endPosition)
    }
  }
  // 改变原生的Animation日期格式，Timeline 的时间格式在源码中修改
  changeTimeLine() {
    var date = new Date()
    // 可返回格林威治时间和本地时间之间的时差
    var h = 0 - date.getTimezoneOffset()
    this.viewer.animation.viewModel.timeFormatter = function(date, viewModel) {
      // 重新构造一个当前系统时间的儒略日
      var dateZone = Cesium.JulianDate.addMinutes(date, h, new Cesium.JulianDate())
      var gregorianDate = Cesium.JulianDate.toGregorianDate(dateZone)
      var millisecond = Math.round(gregorianDate.millisecond)
      // 倍速是否小于 1, 小于 1 则显示毫秒级
      if (Math.abs(viewModel._clockViewModel.multiplier) < 1) {
        return Cesium.sprintf('%02d:%02d:%02d.%03d', gregorianDate.hour, gregorianDate.minute, gregorianDate.second, gregorianDate.millisecond)
      }
      return Cesium.sprintf('%02d:%02d:%02d', gregorianDate.hour, gregorianDate.minute, gregorianDate.second)
    }
    // 设置日期
    this.viewer.animation.viewModel.dateFormatter = function(date, viewModel) {
      var dateZone = Cesium.JulianDate.addMinutes(date, h, new Cesium.JulianDate())
      var gregorianDate = Cesium.JulianDate.toGregorianDate(dateZone)
      // 设置格式为 xx/xx/xx, 格式可自定义为任意你想要的
      return Cesium.sprintf('%4d/%02d/%02d', gregorianDate.year, gregorianDate.month, gregorianDate.day)
    }
  }
  dynamicChangeTime() {
    var that = this
    var startTime = this.viewer.clock.startTime
    var stopTime = this.viewer.clock.stopTime
    function tick() {
      var currentTime = Cesium.JulianDate.clone(that.viewer.clock.currentTime)
      if (Cesium.JulianDate.greaterThan(currentTime, stopTime)) {
        startTime = Cesium.JulianDate.addDays(startTime, 1.0, startTime)
        stopTime = Cesium.JulianDate.addDays(stopTime, 1.0, stopTime)
        that.viewer.timeline.zoomTo(startTime, stopTime)
      }
      Cesium.requestAnimationFrame(tick)
    }
    Cesium.requestAnimationFrame(tick)
  }
  // 飞行
  flyto(lat, lon, hight) {
    this.viewer.camera.flyTo({
      destination: Cesium.Cartesian3.fromDegrees(lat, lon, hight),
      orientation: {
        // direction: new Cesium.Cartesian3(0.04231243104240401,0.20123236049443421,0.97862924300734),
        // up: new Cesium.Cartesian3(0.47934589305293746,0.8553216253114552,0.1966022179118339)
        // heading : Cesium.Math.toRadians(0), // 方向
        // pitch : Cesium.Math.toRadians(-90.0),// 倾斜角度
        // roll : 0
      }
    })
  }
  /**
   * @description: iexplorer 中飞行的方法，使用earth.iCamera.viewPoint 可以获取当前position
   * @param {position: 位置对象; duration: 飞行持续时间; delayTime: 延时时间}
   * @return:
   */
  IEflyTo(position, duration = 3, delayTime = 0) {
    let that = this
    if (position) {
      setTimeout(() => {
        that.viewer.iCamera.flyTo(
          {
            lon: position.lon,
            lat: position.lat,
            alt: position.alt,
            heading: position.heading,
            pitch: position.pitch,
            roll: position.roll
          },
          duration
        )
      }, delayTime)
    }
  }
  // 切换底图
  changeBaseLayer(option) {
    if (this.baseImageLayer) {
      this.viewer.imageryLayers.remove(this.baseImageLayer)
      this.baseImageLayer = null
    }
    this.baseImageLayer = this.addLayer(option)
    this.viewer.imageryLayers.lowerToBottom(this.baseImageLayer)
    this.viewer.imageryLayers.raise(this.baseImageLayer)
  }
  //添加图层
  addLayer(option) {
    switch (option.type) {
      case 'tms':
        return this.addTMSLayer(option)
        break
      case 'wmts':
        return this.addWMTSLayer(option)
        break
      case 'urlTemp':
        return this.addURLTempLayer(option)
        break
      default:
        break
    }
  }
  // 指定url的format模版添加图层
  addURLTempLayer(option) {
    let _layer = this.viewer.imageryLayers.addImageryProvider(
      new Cesium.UrlTemplateImageryProvider({
        url: option.url ? option.url : ''
      })
    )
    _layer.name = option.name ? option.name : ''
    return _layer
  }

  // TMS
  addTMSLayer(option) {
    let _layer = this.viewer.imageryLayers.addImageryProvider(
      new Cesium.createTileMapServiceImageryProvider({
        url: option.url ? option.url : '',
        tilingScheme: new Cesium.GeographicTilingScheme() //地图平铺方案，前面墨卡托，后面平铺 WebMercatorTilingScheme  GeographicTilingScheme
      })
    )
    _layer.name = option.name ? option.name : ''
    return _layer
  }
  // MWTS
  addWMTSLayer(option) {
    let _layer = this.viewer.imageryLayers.addImageryProvider(
      new Cesium.WebMapTileServiceImageryProvider({
        url: option.url ? option.url : '',
        layer: option.layer ? option.layer : '',
        style: 'default',
        format: option.format ? option.format : 'image/jpeg',
        tileMatrixSetID: option.tileMatrixSetID ? option.tileMatrixSetID : 'EPSG:4326'
      })
    )
    _layer.name = option.name ? option.name : ''
    return _layer
  }
  // 管道
  addToolbarButton() {
    let that = this
    that.group = new GV.GraphicGroup()
    that.viewer.graphicLayer.add(that.group)
    // 管道
    let volumePolylineGraphic = new GV.VolumePolylineGraphic({
      visible: true,
      positions: [new GV.GeoPoint(0, 0, 100000), new GV.GeoPoint(20, 10, 10000)],
      shape: GV.GeoPoint.unpackArray([
        [0, -50000],
        [15450.84971874737, -47552.82581475768],
        [29389.262614623658, -40450.84971874737],
        [40450.84971874737, -29389.26261462365],
        [47552.82581475768, -15450.849718747373],
        [50000, 8.040613248383182e-12],
        [47552.82581475768, 15450.849718747379],
        [40450.84971874737, 29389.26261462365],
        [29389.26261462366, 40450.84971874737],
        [15450.849718747357, 47552.825814757685],
        [-1.6081226496766365e-11, 50000],
        [-15450.849718747386, 47552.82581475768],
        [-29389.26261462367, 40450.84971874736],
        [-40450.84971874737, 29389.26261462366],
        [-47552.82581475768, 15450.849718747379],
        [-50000, 9.184850993605149e-12],
        [-47552.825814757685, -15450.849718747362],
        [-40450.84971874735, -29389.262614623683],
        [-20336.83215379001, -45677.27288213005],
        [-5226.423163382671, -49726.09476841366]
      ]),
      cornerType: 'rounded',
      fill: true,
      outline: false,
      outlineWidth: 1,
      outlineColor: '#40B4DB',
      color: 'rgba(77, 216, 255, 0.4)'
    })
    that.group.add(volumePolylineGraphic)
  }
  // 移除管道
  removeToolbarButton() {
    this.group.clear()
  }

  /**
   * 飞机
   * @param {*} status 飞机状态
   */
  addPlanePath(geoPoints, status) {
    this.removePlane()
    let that = this
    // const start = new GV.GeoPoint(0, 0, 100000)
    // const end = new GV.GeoPoint(20, 10, 10000)
    const factor = 30
    //飞机
    that.modelGraphic = new GV.ModelGraphic({
      url: './dist/resources/model/satelliteDemo/Cesium_Air.glb',
      position: geoPoints[0],
      scale: 70
    })
    that.viewer.graphicLayer.add(that.modelGraphic)
    //计算差分点以及时间
    // const positions = GV.Calculate.getParabola(start, end, factor, 40, that.viewer)
    // const positions = GV.Calculate.getBezier(geoPoints)
    const positionsInfo = []
    let time = 0
    for (const point of geoPoints) {
      positionsInfo.push({ point: point, time: time })
      time += 5
    }
    const path = new GV.Path(that.viewer)
    path.pathPositions = positionsInfo
    //回调函数根据时间返回对应的主模型的位置和姿态
    path.callback = (position, heading, pitch, roll) => {
      that.modelGraphic.position = position
      that.modelGraphic.heading = heading
      that.modelGraphic.pitch = pitch
      that.modelGraphic.roll = roll
    }
    path.start()
    //  开始/结束动画
    // if (status) {
    //   path.start()
    // } else {
    //   path.stop()
    // }
  }
  // 移除模型
  removePlane() {
    if (!this.modelGraphic) return false
    this.viewer.graphicLayer.remove(this.modelGraphic)
  }
  /**
   * @description: 添加Kml数据
   * @param
   */
  addKmlDataSource(url, name, color, type, event) {
    let that = this
    Cesium.KmlDataSource.load(url, {
      camera: that.viewer.scene.camera,
      canvas: that.viewer.scene.canvas
    }).then(function(dataSource) {
      let entities = dataSource.entities.values
      for (let i = 0; i < entities.length; ++i) {
        // let positions = entities[i].polyline.hierarchy._value.positions
        // entities[i].polygon = undefined
        // entities[i].polyline = new Cesium.PolylineGraphics({
        //   positions: [...positions, positions[0]],
        //   width: 3,
        //   material: Cesium.Color.fromCssColorString('rgb(255,0,0)'),
        //   clampToGround: true
        // })
        // if (type && event) {
        //   entities[i][type] = event
        // }
        // entities[i].name = name
        entities[i].cursor = true
      }

      that.dataJson[url] = dataSource
      that.viewer.dataSources.add(dataSource)
      // that.viewer.zoomTo(dataSource)
    })
  }
  addTriangleMeshGraphic() {
    let data = {
      points: [
        100,
        37.26485134792725,
        0,
        118.3285382401569,
        37.08646598318436,
        0,
        118.7172125631428,
        37.20312661929784,
        0,
        118.5539223077147,
        37.35018476556944,
        0,
        118.7172125631428,
        37.20312661929784,
        10000,
        118.5539223077147,
        37.35018476556944,
        10000
      ],
      indices: [0, 1, 2, 3, 4, 5]
    }
    let opt = new GV.TriangleMeshGraphicOpt()
    opt.color = '#00CED1'
    opt.dataSource = { points: data.points, indices: data.indices }
    let TMesh = new GV.TriangleMeshGraphic(opt)
    let obj = this.viewer.graphicLayer.add(TMesh)
    // this.flyto(118.279864040361)
  }
  // 世界坐标转地理坐标  cartesian3 转 经纬度
  cartesian3ToCartographic(cartesian3) {
    var car = this.viewer.scene.globe.ellipsoid.cartesianToCartographic(cartesian3)
    var lon = Cesium.Math.toDegrees(car.longitude)
    var lat = Cesium.Math.toDegrees(car.latitude)
    return [lon, lat]
  }
  // 屏幕坐标转地理坐标  cartesian2 -> cartesian3 -> 经纬度
  cartesian2ToCartographic(cartesian2) {
    let cartesian3 = this.viewer.scene.globe.pick(this.viewer.camera.getPickRay(cartesian2), this.viewer.scene)
    return this.cartesian3ToCartographic(cartesian3)
  }
}
export default Earth
